--- permalink: /nb/parcoursup/ layout: nb author_profile: false toc: true toc_label: Sommaire toc_sticky: true --- {% raw %}

Statistiques sur Parcoursup

Étude des données des affectations post-bac pour la rentrée 2021, qui apportent beaucoup de nouveautés : nouveau bac, nouvelle plateforme Parcoursup et nouvelle filière MP2I (maths-physique-informatique) en CPGE

Chargement des données

Chargeons les données sur https://data.enseignementsup-recherche.gouv.fr/pages/home/?flg=fr, en ne conservant que les colonnes les plus intéressantes et en les renommant pour plus de clarté :

In [1]:
import pandas as pd
import plotly.express as px

df = pd.read_csv("https://data.enseignementsup-recherche.gouv.fr/explore/dataset/fr-esr-parcoursup/download/?format=csv&timezone=Europe/Berlin&lang=fr&use_labels_for_header=true&csv_separator=%3B", sep=";") \
    .iloc[:, [110, 3, 5, 7, 8, 9, 17, 45, 60, 61, 62, 63, 101, 107]] \
    .rename(columns={"Effectif total des candidats pour une formation": "Candidats", "Dont effectif des admis néo bacheliers sans mention au bac": "Sans Mention", "Dont effectif des admis néo bacheliers avec mention Assez Bien au bac": "Mention Assez Bien", "Dont effectif des admis néo bacheliers avec mention Bien au bac": "Mention Bien", "Dont effectif des admis néo bacheliers avec mention Très Bien au bac": "Mention Très Bien", "Rang du dernier appelé du groupe 1": "Rang dernier appelé", "Taux d’accès des candidats ayant postulé à la formation (ratio entre le dernier appelé et le nombre vœux PP)": "Taux d'accès", "LIB_FOR_VOE_INS": "Filière", "Effectif total des candidats ayant accepté la proposition de l’établissement (admis)": "Effectif"}) \
    .dropna()
df = df.query("Effectif != 0") # supprime les formations avec 0 élève
df["Filière"][df["Filière"].str.contains("Sportive")] = "STAPS"
df["Filière"][df["Filière"] == "Concours Première année"] = "Concours véto"
df["Filière"] = df["Filière"].str.slice(0, 30)  # raccourcir les noms de filières
df["Taux d'accès"] = df["Taux d'accès"]*df["Effectif"]

Pour la suite, je créé df_filiere qui agrège les données par filière et df_cpge qui contient seulement les filières de CPGE :

In [2]:
mentions = ["Sans Mention", "Mention Assez Bien", "Mention Bien", "Mention Très Bien"]
col = mentions + ["Taux d'accès", "Effectif", "Candidats"]
df_filiere = df.groupby("Filière").agg(dict({s: "sum" for s in col}))
df_filiere["Nombre"] = df.groupby("Filière").size() # nombre de classes de chaque filière
df_filiere[mentions] = df_filiere[mentions].div(df_filiere[mentions].sum(axis=1), axis=0) # pourcentage de mentions par filière
df_filiere["Taux d'accès"] /= df_filiere["Effectif"]
df_cpge = df_filiere[df_filiere.index.str.contains("CPGE")]

Statistiques générales

In [3]:
df.describe()
Out[3]:
Candidats Effectif Sans Mention Mention Assez Bien Mention Bien Mention Très Bien Rang dernier appelé Taux d'accès
count 12556.000000 12556.000000 12556.000000 12556.000000 12556.000000 12556.000000 12556.000000 12556.000000
mean 888.427764 49.622571 9.378305 13.406977 9.356722 3.760672 408.719975 2884.845811
std 1389.795590 82.768841 18.699998 25.242332 21.355621 13.546956 976.927026 5990.687102
min 3.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 2.000000
25% 198.000000 15.000000 2.000000 3.000000 1.000000 0.000000 31.000000 609.000000
50% 418.000000 27.000000 5.000000 7.000000 4.000000 1.000000 94.000000 1150.000000
75% 934.000000 47.000000 10.000000 13.000000 9.000000 2.000000 353.000000 2450.000000
max 18190.000000 1569.000000 363.000000 532.000000 556.000000 444.000000 15836.000000 145200.000000

On observe que l'effectif moyen dans une formation est environ 50, avec un maximum de 1569 pour la formation suivante :

In [4]:
df.iloc[[df["Effectif"].argmax()]]
Out[4]:
Filière Établissement Département de l’établissement Académie de l’établissement Commune de l’établissement Sélectivité Candidats Effectif Sans Mention Mention Assez Bien Mention Bien Mention Très Bien Rang dernier appelé Taux d'accès
13063 Licence - Portail Droit - parc Université Toulouse 1 Capitole Haute-Garonne Toulouse Toulouse formation non sélective 8385 1569 344 532 329 71 6215.0 112968.0

Effectifs

Voici les 20 formations avec le plus gros effectif :

In [5]:
df_gros = df_filiere.sort_values("Effectif", ascending=False)[:20]
px.pie(df_gros, values="Effectif", names=df_gros.index, title="Pourcentage des effectifs par formation") \
  .show(renderer="notebook")

Filière de CPGE avec le plus de classes :

In [6]:
df_cpge_gros = df_cpge.sort_values("Nombre", ascending=False)[:11]
px.pie(df_cpge_gros, values="Nombre", names=df_cpge_gros.index, title="Nombre de classes par filière de CPGE") \
  .show(renderer="notebook")

Nombre de candidatures

Voici les filières avec un nombre de candidature par place le plus élevé :

In [7]:
df_candidats = df_filiere[["Candidats"]].div(df_filiere["Effectif"], axis=0).sort_values(by="Candidats", ascending=False)[:10]
px.bar(df_candidats, title="Nombre de candidatures par place") \
  .show(renderer="notebook")
In [8]:
df_candidats = df_cpge[["Candidats"]].div(df_filiere["Effectif"], axis=0).sort_values(by="Candidats", ascending=False)[:10]
px.bar(df_candidats, title="Nombre de candidatures par place en CPGE") \
  .show(renderer="notebook")

Pourcentage de mentions au bac

In [9]:
df_m = df_filiere[mentions].loc[df_gros.index].sort_values(by="Mention Très Bien", ascending=False)
px.bar(df_m, title="Pourcentage de mentions par formation") \
  .show(renderer="notebook")
In [10]:
df_m = df_cpge[mentions].loc[df_cpge_gros.index].sort_values(by="Mention Très Bien", ascending=False)
px.bar(df_m, title="Pourcentage de mentions par filière de CPGE") \
  .show(renderer="notebook")

Taux d'accès

In [11]:
px.bar(df_gros["Taux d'accès"].sort_values(), title="Taux d'accès moyen (%) des plus grosses formations") \
  .show(renderer="notebook")
In [12]:
px.bar(df_cpge["Taux d'accès"].sort_values(), title="Taux d'accès moyen (%) de chaque filière de CPGE") \
  .show(renderer="notebook")
{% endraw %}